﻿// =============================================
// 文件保护宏：防止该头文件（或 Meta Pass 代码）被重复包含
// 如果尚未定义 CUSTOM_META_PASS_INCLUDED，则定义它并继续，否则跳过该部分代码的编译
// =============================================
#ifndef CUSTOM_META_PASS_INCLUDED
#define CUSTOM_META_PASS_INCLUDED

// =============================================
// 引入自定义 Shader 库中的核心模块，用于获取材质属性、光照、BRDF 等功能
// 这些模块通常包括：Surface 定义、GetBase、GetMetallic、GetSmoothness、GetEmission、GetBRDF 等
// =============================================
#include "../ShaderLibrary/Surface.hlsl"   // 定义 Surface 结构体及相关工具
#include "../ShaderLibrary/Shadows.hlsl"   // 可能包含一些辅助功能（虽然 Meta Pass 通常不用阴影）
#include "../ShaderLibrary/Light.hlsl"     // 可能包含光源相关定义（本 Pass 可能未直接使用）
#include "../ShaderLibrary/BRDF.hlsl"      // 提供 BRDF 相关计算，如 GetBRDF(...)

// =============================================
// Unity 在 Meta Pass 中传入的控制参数，用于告诉 Shader 当前是在计算：
// - .x → 是否计算漫反射与高光对间接光的贡献（用于 Lightmap）
// - .y → 是否计算自发光（Emission）贡献
// 这两个布尔值控制 Meta Pass 的输出内容分支
// =============================================
bool4 unity_MetaFragmentControl;

// =============================================
// Unity 提供的用于控制最终输出亮度的参数：
// - unity_OneOverOutputBoost：用于对输出颜色进行 Pow 限制的系数（控制亮度提升）
// - unity_MaxOutputValue：输出颜色的最大允许值，避免过曝
// =============================================
float unity_OneOverOutputBoost;
float unity_MaxOutputValue;

// =============================================
// 定义顶点着色器的输入结构体：Attributes
// 包括：
// - positionOS：物体空间中的顶点位置（用于 Meta 位置变换）
// - baseUV：基础贴图的 UV 坐标（用于采样 Albedo / BaseColor）
// - lightMapUV：光照贴图的 UV 坐标（可能用于某些特殊用途，但在此未直接使用）
// =============================================
struct Attributes {
	float3 positionOS : POSITION;      // 物体空间中的顶点位置
	float2 baseUV : TEXCOORD0;         // 基础贴图 UV（通常用于 Albedo 贴图）
	float2 lightMapUV : TEXCOORD1;     // 光照贴图 UV（通常未直接使用，但保留）
};

// =============================================
// 定义顶点着色器的输出 / 片段着色器的输入结构体：Varyings
// 包括：
// - positionCS：裁剪空间中的顶点位置（用于渲染一个全屏四边形或简单几何体）
// - baseUV：传递给片段着色器的基础贴图 UV，用于采样材质属性
// =============================================
struct Varyings {
	float4 positionCS : SV_POSITION;   // 裁剪空间中的顶点位置
	float2 baseUV : VAR_BASE_UV;       // 基础贴图 UV，用于采样材质属性
};

// =============================================
// 顶点着色器：MetaPassVertex
// 作用：将物体空间顶点位置进行简单处理（比如 Z 轴设为 0 或极小值），并变换到裁剪空间
// 同时传递基础 UV 到片段着色器
// =============================================
Varyings MetaPassVertex(Attributes input) {
	Varyings output;

	// 特殊处理：将输入的 positionOS.xy 替换为 lightMapUV 经过 Lightmap ST 变换后的值
	// 这一步通常是为了让 Meta Pass 渲染的几何体能够正确对齐到 Lightmap 的 UV 空间
	// （但此写法不常见，也可能是为了特殊目的，比如让 Meta 几何覆盖整个 Lightmap 区域）
	input.positionOS.xy =
		input.lightMapUV * unity_LightmapST.xy + unity_LightmapST.zw;

	// 将 Z 轴设为一个极小值（FLT_MIN）或者 0.0，目的是让该物体位于摄像机的近裁剪面附近
	// 但不影响烘焙（因为 Meta Pass 不进入最终渲染）
	input.positionOS.z = input.positionOS.z > 0.0 ? FLT_MIN : 0.0;

	// 将处理后的物体空间顶点位置变换到裁剪空间（用于渲染一个平面或全屏四边形）
	output.positionCS = TransformWorldToHClip(input.positionOS);

	// 对基础 UV 进行可能的缩放偏移处理（比如通过 TransformBaseUV 函数，定义于 ShaderLibrary）
	output.baseUV = TransformBaseUV(input.baseUV);

	return output;
}

// =============================================
// 片段着色器：MetaPassFragment
// 作用：根据 unity_MetaFragmentControl 的值，输出该物体在烘焙阶段应该贡献的：
// - 漫反射 + 高光（用于间接光照计算 / Lightmap）
// - 或 自发光（Emission）
// =============================================
float4 MetaPassFragment(Varyings input) : SV_TARGET {
	// 从基础 UV 采样物体的基础颜色（Albedo / BaseColor），通常是贴图采样结果
	float4 base = GetBase(input.baseUV);

	// 定义一个 Surface 结构体，并初始化为零（避免未初始化警告）
	Surface surface;
	ZERO_INITIALIZE(Surface, surface);

	// 填充 Surface 的关键属性，这些属性将被用于计算 BRDF 与 Meta 输出
	surface.color = base.rgb; // 基础颜色（RGB）
	surface.metallic = GetMetallic(input.baseUV);     // 金属度（来自贴图或参数）
	surface.smoothness = GetSmoothness(input.baseUV); // 光滑度（控制高光锐利度与反射模糊）

	// 基于 Surface 信息，计算 BRDF 相关数据（漫反射与高光反射部分）
	BRDF brdf = GetBRDF(surface);

	// 初始化最终的 Meta 输出颜色为黑色
	float4 meta = 0.0;

	// =========================================
	// Case 1：如果 unity_MetaFragmentControl.x 为 true
	// 表示当前需要计算该物体对 **间接光照（Lightmap / 全局光照）的贡献**
	// 即输出它的漫反射颜色 + 高光颜色（通常用于烘焙间接光）
	// =========================================
	if (unity_MetaFragmentControl.x) {
		// meta.rgb = 漫反射颜色（brdf.diffuse），alpha = 1.0
		meta = float4(brdf.diffuse, 1.0);

		// 添加高光对间接光照的贡献：高光颜色 × 粗糙度 × 0.5（经验值，用于模拟间接高光）
		meta.rgb += brdf.specular * brdf.roughness * 0.5;

		// 对输出颜色进行亮度控制：
		// 1. 使用 PositivePow 对颜色进行伽马校正风格的调整（基于 unity_OneOverOutputBoost）
		// 2. 使用 min 函数限制最大值不超过 unity_MaxOutputValue，防止过曝
		meta.rgb = min(
			PositivePow(meta.rgb, unity_OneOverOutputBoost), 
			unity_MaxOutputValue
		);
	}
	// =========================================
	// Case 2：如果 unity_MetaFragmentControl.y 为 true
	// 表示当前需要计算该物体的 **自发光（Emission）**，用于烘焙发光物体或影响场景间接光
	// =========================================
	else if (unity_MetaFragmentControl.y) {
		// meta = 自发光颜色（RGBA），通常来自贴图或参数，alpha = 1.0
		meta = float4(GetEmission(input.baseUV), 1.0);
	}

	// 返回最终的 Meta 颜色，用于 Unity 光照烘焙系统
	return meta;
}

// =============================================
// 文件保护宏结束
// =============================================
#endif